package com.example.java.base.jdk8.stream;

import cn.hutool.core.util.StrUtil;
import com.example.java.base.jdk8.stream.entity.User;
import com.example.java.base.jdk8.stream.entity.UserDto;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * StreamTest3:Stream常用API,类似MySQL操作一样
 *
 * @author zhangxiaoxiang
 * @date 2021/01/10
 */
public class StreamTest3 {
    public static void main(String[] args) {
        System.out.println("--------------forEach----------------");
        forEach();
        System.out.println("--------------filter----------------");
        filter();
        System.out.println("--------------map----------------");
        map();
        System.out.println("--------------count----------------");
        count();
        System.out.println("--------------limit----------------");
        limit();
        System.out.println("--------------skip----------------");
        skip();
        System.out.println("--------------concat----------------");
        concat();
        System.out.println("--------------toMap()----------------");
        toMap();
    }

    public static void forEach() {
        Stream<String> stream = Stream.of("长草颜团子", "鲁班七号", "诸葛亮", "甄姬");
        stream.forEach(name -> System.out.println("name = " + name));
    }

    public static void filter() {
        //创建一个Stream流
        Stream<String> stream = Stream.of("张三丰", "张翠山", "赵敏", "周芷若", "张无忌");
        //对Stream流中的元素进行过滤,只要姓张的人
        Stream<String> stream2 = stream.filter((String name) -> name.startsWith("张"));
        //遍历stream2流(使用的方法引用)
        stream2.forEach(System.out::println);

        /**
         * 再次遍历 IllegalStateException: stream has already been operated upon or closed
         * Stream流属于管道流,只能被消费(使用)一次,第一个Stream流调用完毕方法,数据就会流转到下一个Stream上,
         * 而这时第一个Stream流已经使用完毕,就会关闭了,所以第一个Stream流就不能再调用方法了
         */
        // stream.forEach(name -> System.out.println(name));
    }

    public static void map() {
        //获取一个String类型的Stream流
        Stream<String> stream = Stream.of("1", "2", "3", "4");
        //使用map方法,把字符串类型的整数,转换(映射)为Integer类型的整数
        Stream<Integer> stream2 = stream.map(Integer::parseInt);
        //遍历Stream2流
        stream2.forEach(System.out::println);


    }

    public static void count() {
        //获取一个Stream流
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        list.add(6);
        list.add(7);
        Stream<Integer> stream = list.stream();
        long count = stream.count();
        //7
        System.out.println(count);
    }

    public static void limit() {
        //获取一个Stream流
        String[] arr = {"美羊羊", "喜洋洋", "懒洋洋", "灰太狼", "红太狼"};
        Stream<String> stream = Stream.of(arr);
        //使用limit对Stream流中的元素进行截取,只要前3个元素
        Stream<String> stream2 = stream.limit(3);
        //遍历stream2流
        stream2.forEach(System.out::println);
    }

    public static void skip() {
        //获取一个Stream流
        String[] arr = {"美羊羊", "喜洋洋", "懒洋洋", "灰太狼", "红太狼"};
        Stream<String> stream = Stream.of(arr);
        //使用skip方法跳过前3个元素
        Stream<String> stream2 = stream.skip(3);
        //遍历stream2流
        stream2.forEach(System.out::println);
    }

    public static void concat() {
        //创建一个Stream流
        Stream<String> stream1 = Stream.of("张三丰", "张翠山", "赵敏", "周芷若", "张无忌");
        //获取一个Stream流
        String[] arr = {"美羊羊", "喜洋洋", "懒洋洋", "灰太狼", "红太狼"};
        Stream<String> stream2 = Stream.of(arr);
        //把以上两个流组合为一个流
        Stream<String> concat = Stream.concat(stream1, stream2);
        //遍历concat流
        concat.forEach(System.out::println);
    }

    /**
     * 测试tomap
     */
    public static void toMap() {
        User user1 = User.builder().id("1").name("张三1").addr("重庆1").managerId("mid-" + 1).build();
        User user2 = User.builder().id("2").name("张三2").addr("重庆2").managerId("mid-" + 2).build();
        User user3 = User.builder().id("3").name("张三3").addr("重庆3").managerId(null).build();
        User user4 = User.builder().id("4").name("张三4").addr("重庆4").managerId("mid-" + 4).build();
        User user5 = User.builder().id("5").name("张三5").addr(null).managerId("").build();
        List<User> list = new ArrayList<>();
        list.add(user1);
        list.add(user2);
        list.add(user3);
        list.add(user4);
        list.add(user5);
        //主要构造一个集合
        Map<String, String> idVSName = list.stream().collect(Collectors.toMap(User::getId, User::getName));
        //这相当于SQL查询主要字段
        idVSName.forEach((k, v) -> System.out.println(k + "--->>>" + v));
        //id对应用户
        Map<String, User> userMap = new HashMap<>(16);
        userMap.put(user1.getId(), user1);
        userMap.put(user2.getId(), user2);
        userMap.put(user3.getId(), user3);
        userMap.put(user4.getId(), user4);
        userMap.put(user5.getId(), user5);

        //测试对象转换(分组-对弈数据)
        Map<String, List<UserDto>> collect = userMap.keySet().stream().map(userId -> {
            //待转换数据
            UserDto userDto = new UserDto();
            //数据源
            User user = userMap.get(userId);
            //开始转换
            userDto.setId(userId);
            userDto.setManagerId(user.getManagerId());
            userDto.setName(user.getName());
            return userDto;
            //    过滤
        }).filter((user)-> StrUtil.isNotBlank(user.getManagerId()))
                //分组类似map的key
                .collect(Collectors.groupingBy(UserDto::getManagerId));
        System.out.println("过滤后(getManagerId=null或者空字符串)......");
        collect.forEach((id, ud) -> System.out.println("id=" + id + "  " + ud));
        //s 对应Map<String, List<UserDto>>key,mv对应value的值,这里是集合
        List<String> list1=new ArrayList<>();
        collect.forEach((s,as)->{
            as.forEach(
                    //a只是个形参,类型是UserDto,List<UserDto>转成的流
                    a->{
                        //添加id集合
                        list1.add(a.getId());

                    }

            );
        });
        //遍历打印id
        list1.forEach(System.out::println);
    }

}
